package com.lex.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.lex.common.api.CommonResult;
import com.lex.data.admin.mapper.LexCmsMenuMapper;
import com.lex.data.admin.mapper.LexCmsRoleMenuMapper;
import com.lex.data.admin.model.LexCmsMenu;
import com.lex.data.admin.model.LexCmsRoleMenu;
import com.lex.data.admin.model.LexCmsUsers;
import com.lex.entity.menu.MenuListVo;
import com.lex.entity.menu.MenuRouterVo;
import com.lex.entity.menu.MetaVo;
import com.lex.entity.params.MenuQueryParams;
import com.lex.mapper.UserRoleMenu;
import com.lex.service.BaseService;
import com.lex.service.MenuService;
import com.lex.util.MyContext;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Slf4j
@Service
public class MenuServiceImpl implements MenuService {

    @Resource
    private BaseService baseService;

    @Resource
    private UserRoleMenu userRoleMenu;

    @Resource
    private LexCmsMenuMapper lexCmsMenuMapper;

    @Resource
    private LexCmsRoleMenuMapper lexCmsRoleMenuMapper;
    /**
     * 循环递归处理数据，将数据处理成树形结构
     * @param menuList
     * @param parentId
     * @return MenuDto
     */
    private List<MenuRouterVo> buildMenuTree(List<LexCmsMenu> menuList, Integer parentId){
        List<MenuRouterVo> treeList = new ArrayList<MenuRouterVo>();
        for (LexCmsMenu menu : menuList) {
//            if(menu.getIsShow() == 0){
//                continue;
//            }
            MenuRouterVo loginMenuDto = new MenuRouterVo();
            MetaVo metaVo = new MetaVo();
            loginMenuDto.setName(menu.getName());
            loginMenuDto.setPath(menu.getPath());
            loginMenuDto.setComponent(menu.getComponent());
            //meta
            metaVo.setTitle(menu.getName());
            metaVo.setIcon(menu.getIcon());
            metaVo.setHideMenu(menu.getIsShow() != 1);
            metaVo.setCurrentActiveMenu(menu.getCurrentActiveMenu());
            metaVo.setRealPath(menu.getRealPath());
            metaVo.setCarryParam(menu.getCarryParam() != 0);
            metaVo.setIgnoreKeepAlive(true);
            //meta end
            loginMenuDto.setMeta(metaVo);
            if (menu.getParentId().equals(parentId)) {
                loginMenuDto.setChildren(buildMenuTree(menuList, menu.getId().intValue()).isEmpty()
                        ? null
                        : buildMenuTree(menuList, menu.getId().intValue()));
                treeList.add(loginMenuDto);
            }
        }
        return treeList;
    }

    /**
     * 根据用户名获取不同的菜单列表，多个函数用到该功能，所以提取出来
     * @param username
     * @return
     */
    private List<LexCmsMenu> getUserMenuListByName(String username) {
        LexCmsUsers Userinfo = baseService.getUserInfoByAccount(username);
        if (Userinfo == null) {
            return null;
        }
        //获取用户角色菜单id列表
        List<LexCmsRoleMenu> roleMenuList = userRoleMenu.getUserMenuList(Userinfo.getUserId());
        //获取所有菜单列表，用于过滤，一般redis中保存所有菜单，如果没有则从数据库中获取，菜单变动会更新redis
        List<LexCmsMenu> allMenuList = baseService.getCacheService().getAllResourceList();
        if (allMenuList == null || allMenuList.isEmpty()) {
            allMenuList = lexCmsMenuMapper.selectList(
                    new QueryWrapper<LexCmsMenu>()
//                            .eq("state",1)
//                    .eq("is_show",1)
                    .orderByAsc("order_num"));
            baseService.getCacheService().setAllResourceList(allMenuList);
        }


        List<LexCmsMenu> menuList = allMenuList.stream()
                //过滤id匹配的菜单
                .filter(resource -> roleMenuList.stream()
                        .anyMatch(roleMenu -> roleMenu.getMenuId().equals(resource.getId())))
                //过滤掉按钮
                .filter(resource -> resource.getType() != 2)
                .filter(resource -> resource.getState() == 1)
                .collect(Collectors.toList());;
        return menuList;
    }

    /**
     * 获取用户菜单列表，不同的用户拥有不同的权限，返回的菜单列表也不同
     * @return CommonResult
     */
    @Override
    public CommonResult getUserMenuList() {
        String username = MyContext.getCurrentUserName(); //获取当前请求的用户名
        if (username == null) {
            return CommonResult.failed("获取用户信息失败");
        }
        List<LexCmsMenu> menuList;
        menuList = getUserMenuListByName(username);
        List<MenuRouterVo> TreeMenu;
        TreeMenu =  buildMenuTree(menuList, 0);
        return CommonResult.success(TreeMenu);
    }

    /**
     * 获取用户权限标识，用户权限标识用户前端控制按钮的显示和隐藏
     * @return CommonResult
     */
    @Override
    public CommonResult getUserPermCode() {
        String username = MyContext.getCurrentUserName();
        if (username == null) {
            return CommonResult.failed("获取用户信息失败");
        }
        List<LexCmsMenu> permCodeList;
        permCodeList = getUserMenuListByName(username);
        List<String> permCode = permCodeList == null ?
                List.of()
                : permCodeList.stream().map(
                LexCmsMenu::getCode
                ).filter(
                        code -> !"".equals(code)
                ).collect(Collectors.toList());
        return CommonResult.success(permCode);
    }

    /**
     * 获取所有菜单列表
     * @param queryParams
     * @param pageSize
     * @param page
     * @return CommonResult
     */
    @Override
    public CommonResult getAllMenuList(MenuQueryParams queryParams, Integer pageSize, Integer page) {
        //获取所有菜单列表的缓存
        List<LexCmsMenu> allMenuList = baseService.getCacheService().getMenuList();
        if (allMenuList == null || allMenuList.isEmpty()) {
            //不管是否显示和状态是否为1，全部查询放到缓存中
            allMenuList = lexCmsMenuMapper.selectList(
                    new QueryWrapper<LexCmsMenu>()
                            .orderByAsc("order_num"));
            baseService.getCacheService().setMenuList(allMenuList);
        }
        Stream<LexCmsMenu> menuStream = allMenuList.stream(); //转换成流
        //过滤菜单名称
        if (queryParams.getMenuName() != null) {
            menuStream = menuStream
                    .filter(menu -> menu.getName().contains(queryParams.getMenuName())
                        || menu.getName().startsWith(queryParams.getMenuName())
                            || menu.getName().endsWith(queryParams.getMenuName())
                    );
        }
        //过滤菜单状态
        if (queryParams.getStatus() != null) {
            menuStream = menuStream
                    .filter(menu -> menu.getState().equals(queryParams.getStatus()));
        }

        List<LexCmsMenu> menuList = menuStream
//                .skip((long) (page - 1) * pageSize)
//                .limit(pageSize)
                .toList();
        List<MenuListVo> TreeMenu = new ArrayList<>();
        if (menuList.size() == 1){
            MenuListVo menu = new MenuListVo();
            menu.setId(menuList.get(0).getId());
            menu.setPath(menuList.get(0).getPath());
            menu.setMenuName(menuList.get(0).getName());
            menu.setComponent(menuList.get(0).getComponent());
            menu.setRedirect("".equals(menuList.get(0).getRedirect()) ? null : menuList.get(0).getRedirect());
            menu.setOrderNo(menuList.get(0).getOrderNum());
            menu.setIcon(menuList.get(0).getIcon());
            menu.setType(String.valueOf(menuList.get(0).getType()));
            menu.setPermission(menuList.get(0).getPermission());
            menu.setCreateTime(String.valueOf(menuList.get(0).getCreateTime()));
            menu.setStatus(String.valueOf(menuList.get(0).getState()));
            menu.setParentMenu(String.valueOf(menuList.get(0).getParentId()));
            menu.setMethod(menuList.get(0).getMethod());
            menu.setShow(menuList.get(0).getIsShow());
            menu.setLabel(menuList.get(0).getName());
            menu.setKey(String.valueOf(menuList.get(0).getId()));
            menu.setValue(String.valueOf(menuList.get(0).getId()));
            menu.setCode(menuList.get(0).getCode());
            menu.setCurrentActiveMenu(menuList.get(0).getCurrentActiveMenu());
            menu.setRealPath(menuList.get(0).getRealPath());
            menu.setCarryParam(menuList.get(0).getCarryParam());
            TreeMenu.add(menu);
        }else{
            TreeMenu = buildAllMenuTree(menuList, 0);
        }
        return CommonResult.success(TreeMenu);
    }

    /**
     * 递归处理数据，将数据处理成树形结构
     * @param menuList
     * @param parentId
     * @return
     */
    private List<MenuListVo> buildAllMenuTree(List<LexCmsMenu> menuList, Integer parentId){
        List<MenuListVo> treeList = new ArrayList<MenuListVo>();
        for (LexCmsMenu menu : menuList) {
            MenuListVo menuDto = new MenuListVo();
            menuDto.setId(menu.getId());
            menuDto.setPath(menu.getPath());
            menuDto.setMenuName(menu.getName());
            menuDto.setComponent(menu.getComponent());
            menuDto.setRedirect("".equals(menu.getRedirect()) ? null : menu.getRedirect());
            menuDto.setOrderNo(menu.getOrderNum());
            menuDto.setIcon(menu.getIcon());
            menuDto.setType(String.valueOf(menu.getType()));
            menuDto.setPermission(menu.getPermission());
            menuDto.setCreateTime(String.valueOf(menu.getCreateTime()));
            menuDto.setStatus(String.valueOf(menu.getState()));
            menuDto.setParentMenu(String.valueOf(menu.getParentId()));
            menuDto.setMethod(menu.getMethod());
            menuDto.setShow(menu.getIsShow());
            menuDto.setLabel(menu.getName());
            menuDto.setKey(String.valueOf(menu.getId()));
            menuDto.setValue(String.valueOf(menu.getId()));
            menuDto.setCode(menu.getCode());
            menuDto.setCurrentActiveMenu(menu.getCurrentActiveMenu());
            menuDto.setRealPath(menu.getRealPath());
            menuDto.setCarryParam(menu.getCarryParam());
            if (menu.getParentId().equals(parentId)) {
                menuDto.setChildren(buildAllMenuTree(menuList, menu.getId().intValue()).isEmpty()
                        ? null
                        : buildAllMenuTree(menuList, menu.getId().intValue()));
                treeList.add(menuDto);
            }
        }
        return treeList;
    }
    /**
     * 删除菜单
     * @param menuId
     * @return int
     */
    @Override
    @Transactional
    public CommonResult deleteMenu(Long menuId) {
        //查询该菜单是否有子菜单，如果有子菜单则不能删除
        QueryWrapper<LexCmsMenu> FindqueryWrapper = new QueryWrapper<>();
        FindqueryWrapper.eq("parent_id", menuId);
        List<LexCmsMenu> menuList = lexCmsMenuMapper.selectList(FindqueryWrapper);
        if (!menuList.isEmpty()) {
           return CommonResult.failed("该菜单下有子菜单，不能删除");
        }
        //删除系统菜单中的菜单
        int count = lexCmsMenuMapper.deleteById(menuId);
        //删除平台角色表中删除菜单
        QueryWrapper<LexCmsRoleMenu> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("menu_id", menuId);
        lexCmsRoleMenuMapper.delete(queryWrapper);
        //删除菜单缓存
        baseService.getCacheService().delMenuList();
        baseService.getCacheService().delAllResourceList();
        return count > 0 ? CommonResult.success("菜单删除成功!") : CommonResult.failed("删除失败");
    }

    /**
     * 添加菜单
     * @param menu
     * @return int
     */
    @Override
    public CommonResult addMenu(LexCmsMenu menu) {
        int count = lexCmsMenuMapper.insert(menu);
        baseService.getCacheService().delAllResourceList();
        baseService.getCacheService().delMenuList();
        return count > 0 ? CommonResult.success("菜单添加成功!") : CommonResult.failed("添加失败");
    }

    /**
     * 修改菜单
     * @param menu
     * @return int
     */
    @Override
    public CommonResult updateMenu(LexCmsMenu menu) {
        int count = lexCmsMenuMapper.updateById(menu);
        baseService.getCacheService().delAllResourceList();
        baseService.getCacheService().delMenuList();
        return count > 0 ? CommonResult.success("菜单修改成功!") : CommonResult.failed("修改失败");
    }

    /**
     * 获取角色所有菜单列表
     * @return CommonResult
     */
    @Override
    public CommonResult getRoleAllMenu() {
        List<LexCmsMenu> allResourceList = baseService.getCacheService().getMenuList();
        if(allResourceList == null || allResourceList.isEmpty()){
            //把resourceIds中包含的资源过滤出来
            QueryWrapper<LexCmsMenu> queryWrapper = new QueryWrapper<>();
            queryWrapper
                    .orderByAsc("order_num");
            List<LexCmsMenu> menuList = lexCmsMenuMapper.selectList(queryWrapper);
            baseService.getCacheService().setMenuList(menuList);
            allResourceList = menuList;
        }
        //平台用户
        Stream<LexCmsMenu> stream = allResourceList.stream()
                .filter(resource -> resource.getState() == 1);
        allResourceList = stream.collect(Collectors.toList());
        List<MenuListVo> menus;
        //构建树形结构
        menus = buildAllMenuTree(allResourceList, 0);
        return CommonResult.success(menus);
    }



}
